/*
 * FaceCat图形通讯框架
 * 著作权编号:2015SR229355+2020SR0266727
 * 上海卷卷猫信息技术有限公司
 */

#include "../../stdafx.h"
#include "../../include/grid/FCGridCell.h"

namespace FaceCat{
	FCGridCellStyle::FCGridCellStyle(){
		m_align = FCHorizontalAlign_Inherit;
		m_autoEllipsis = false;
		m_backColor = FCColor_None;
		m_font = 0;
		m_textColor = FCColor_None;
	}

	FCGridCellStyle::~FCGridCellStyle(){
		if(m_font){
			delete m_font;
			m_font = 0;
		}
	}

	FCHorizontalAlign FCGridCellStyle::getAlign(){
		return m_align;
	}

	void FCGridCellStyle::setAlign(FCHorizontalAlign align){
		m_align = align;
	}

	bool FCGridCellStyle::autoEllipsis(){
		return m_autoEllipsis;
	}

	void FCGridCellStyle::setAutoEllipsis(bool autoEllipsis){
		m_autoEllipsis = autoEllipsis;
	}

	Long FCGridCellStyle::getBackColor(){
		return m_backColor;
	}

	void FCGridCellStyle::setBackColor(Long backColor){
		m_backColor = backColor;
	}

	FCFont* FCGridCellStyle::getFont(){
		return m_font;
	}

	void FCGridCellStyle::setFont(FCFont *font){
		if(font){
			if(!m_font){
				m_font = new FCFont();
			}
			m_font->copy(font);
		}
		else{
			if(m_font){
				delete m_font;
				m_font = 0;
			}
		}
	}

	Long FCGridCellStyle::getTextColor(){
		return m_textColor;
	}

	void FCGridCellStyle::setTextColor(Long textColor){
		m_textColor = textColor;
	}

	void FCGridCellStyle::copy(FCGridCellStyle *style){
		setAutoEllipsis(style->autoEllipsis());
		setBackColor(style->getBackColor());
		setFont(style->getFont());
		setTextColor(style->getTextColor());
		setAlign(style->getAlign());
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////

	FCGridCell::FCGridCell(){
		m_allowEdit = false;
		m_colSpan = 1;
		m_column = 0;
		m_grid = 0;
		m_row = 0;
		m_rowSpan = 1;
		m_style = 0;
		m_tag = 0;
	}

	FCGridCell::~FCGridCell(){
		m_column = 0;
		m_grid = 0;
		m_row = 0;
		if(m_style){
			delete m_style;
			m_style = 0;
		}
		m_tag = 0;
	}

	bool FCGridCell::allowEdit(){
		return m_allowEdit;
	}

	void FCGridCell::setAllowEdit(bool value){
		m_allowEdit = value;
	}

	int FCGridCell::getColSpan(){
		return m_colSpan;
	}

	void FCGridCell::setColSpan(int value){
		m_colSpan = value;
	}

	FCGridColumn* FCGridCell::getColumn(){
		return m_column;
	}

	void FCGridCell::setColumn(FCGridColumn *value){
		m_column = value;
	}

	FCGrid* FCGridCell::getGrid(){
		return m_grid;
	}

	void FCGridCell::setGrid(FCGrid *value){
		m_grid = value;
	}

	String FCGridCell::getName(){
		return m_name;
	}

	void FCGridCell::setName(const String& value){
		m_name = value;
	}

	FCGridRow* FCGridCell::getRow(){
		return m_row;
	}

	void FCGridCell::setRow(FCGridRow *value){
		m_row = value;
	}

	int FCGridCell::getRowSpan(){
		return m_rowSpan;
	}

	void FCGridCell::setRowSpan(int value){
		m_rowSpan = value;
	}

	FCGridCellStyle* FCGridCell::getStyle(){
		return m_style;
	}

	void FCGridCell::setStyle(FCGridCellStyle *value){
		if(value){
			if(!m_style){
				m_style = new FCGridCellStyle;
			}
			m_style->copy(value);
		}
		else{
			if(m_style){
				delete m_style;
				m_style = 0;
			}
		}
	}

	Object FCGridCell::getTag(){
		return m_tag;
	}

	void FCGridCell::setTag(Object value){
		m_tag = value;
	}

	String FCGridCell::getText(){
		return getString();
	}

	void FCGridCell::setText(const String& value){
		setString(value);
	}

	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	int FCGridCell::compareTo(FCGridCell *cell){
		return 0;
	}

	bool FCGridCell::getBool(){
		return false;
	}

	double FCGridCell::getDouble(){
		return 0;
	}

	float FCGridCell::getFloat(){
		return 0;
	}

	int FCGridCell::getInt(){
		return 0;
	}

	Long FCGridCell::getLong(){
		return 0;
	}

	String FCGridCell::getPaintText(){
		return getText();
	}

	void FCGridCell::getAttribute(const String& name, String *value, String *type){
		if (name == L"align"){
            *type = L"enum:FCHorizontalAlign";
            FCGridCellStyle *style = getStyle();
            if (style){
				*value = FCTran::horizontalAlignToStr(style->getAlign());
            }
        }
		else if(name == L"allowedit"){
			*type = L"bool";
            *value = FCTran::boolToStr(allowEdit());
		}
		else if (name == L"autoellipsis"){
            *type = L"bool";
            FCGridCellStyle *style = getStyle();
            if (style){
				*value = FCTran::boolToStr(style->autoEllipsis());
            }
        }
		else if(name == L"backcolor"){
			*type = L"color";
            FCGridCellStyle *style = getStyle();
            if (style){
                *value = FCTran::colorToStr(style->getBackColor());
            }
		}
		else if(name == L"colspan"){
			*type = L"int";
            *value = FCTran::intToStr(getColSpan());
        }
		else if(name == L"font"){
			*type = L"font";
            FCGridCellStyle *style = getStyle();
            if (style && style->getFont()){
                *value = FCTran::fontToStr(style->getFont());
            }
		}
		else if(name == L"textcolor"){
			*type = L"color";
            FCGridCellStyle *style = getStyle();
            if (style){
                *value = FCTran::colorToStr(style->getTextColor());
            }
		}
		else if(name == L"name"){
			*type = L"text";
			*value = getName();
		}
        else if (name == L"rowspan"){
			*type = L"int";
            *value = FCTran::intToStr(getRowSpan());
        }
		else if(name == L"text"){
			*type = L"text";
			*value = getText();
		}
        else{
			*type = L"undefined";
            *value = L"";
        }
	}

	ArrayList<String> FCGridCell::getAttributeNames(){
		ArrayList<String> attributeNames;
		attributeNames.add(L"Align");
		attributeNames.add(L"AllowEdit");
		attributeNames.add(L"AutoEllipsis");
		attributeNames.add(L"BackColor");
		attributeNames.add(L"ColSpan");
		attributeNames.add(L"Font");
		attributeNames.add(L"Name");
		attributeNames.add(L"RowSpan");
		attributeNames.add(L"Text");
		attributeNames.add(L"TextColor");
		return attributeNames;
	}

	String FCGridCell::getString(){
		return L"";
	}

	void FCGridCell::onAdd(){
	}

	void FCGridCell::onPaint(FCPaint *paint, const FCRect& rect, const FCRect& clipRect, bool isAlternate){
		int clipW = clipRect.right - clipRect.left;
        int clipH = clipRect.bottom - clipRect.top;
        if (clipW > 0 && clipH> 0){
			if(m_grid && m_row && m_column){
				String text = getPaintText();
				bool selected = false;
				FCGridSelectionMode selectionMode = m_grid->getSelectionMode();
				if(selectionMode == FCGridSelectionMode_SelectCell){
					ArrayList<FCGridCell*> selectedCells = m_grid->getSelectedCells();
					int cellSize = (int)selectedCells.size();
					for (int i = 0; i < cellSize; i++){
						if (selectedCells.get(i) == this){
							selected = true;
							break;
						}
					}
				}
				else if (selectionMode == FCGridSelectionMode_SelectFullColumn){
					ArrayList<FCGridColumn*> selectedColumns = m_grid->getSelectedColumns();
					int selectedColumnsSize = (int)selectedColumns.size();
					for(int i = 0; i < selectedColumnsSize; i++){
						if(selectedColumns.get(i) == m_column){
							selected = true;
							break;
						}
					}
				}
				else if (selectionMode == FCGridSelectionMode_SelectFullRow){
					ArrayList<FCGridRow*> selectedRows = m_grid->getSelectedRows();
					int selectedRowsSize = (int)selectedRows.size();
					for(int i = 0; i < selectedRowsSize; i++){
						if(selectedRows.get(i) == m_row){
							selected = true;
							break;
						}
					}
				}
				FCFont *font = 0;
                Long backColor = FCColor_None;
                Long textColor = FCColor_None;
				bool autoEllipsis = m_grid->autoEllipsis();

				FCGridRowStyle *rowStyle = m_grid->getRowStyle();
                if (isAlternate){
                    FCGridRowStyle *alternateRowStyle = m_grid->getAlternateRowStyle();
                    if (alternateRowStyle){
                        rowStyle = alternateRowStyle;
                    }
                }
				if(rowStyle){
					if(selectionMode != FCGridSelectionMode_SelectFullRow){
						if (backColor == FCColor_None){
							if (selected){
								backColor = rowStyle->getSelectedBackColor();
							}
							else if (m_row == m_grid->getHoveredRow()){
								backColor = rowStyle->getHoveredBackColor();
							}
							else{
								backColor = rowStyle->getBackColor();
							}
						}
					}
					if(!font){
						font = rowStyle->getFont();
					}
					if (textColor == FCColor_None){
						if (selected){
							textColor = rowStyle->getSelectedTextColor();
						}
						else if (m_row == m_grid->getHoveredRow()){
							textColor = rowStyle->getHoveredTextColor();
						}
						else{
							textColor = rowStyle->getTextColor();
						}
					}
				}

                FCHorizontalAlign horizontalAlign = m_column->getCellAlign();
                if (m_style){
					if (m_style->autoEllipsis()){
                        autoEllipsis = m_style->autoEllipsis();
                    }
					if(m_style->getBackColor() != FCColor_None){
						backColor = m_style->getBackColor();
					}
                    if (m_style->getFont()){
                        font = m_style->getFont();
                    }
					if(m_style->getTextColor() != FCColor_None){
						textColor = m_style->getTextColor();
					}
					if (m_style->getAlign() != FCHorizontalAlign_Inherit){
                        horizontalAlign = m_style->getAlign();
                    }
                }
				
				paint->fillRect(backColor, rect);
				FCSize tSize = paint->textSize(text, font, -1);
				FCRect tRect = {0};
				tRect.left = rect.left + 1;
				tRect.top = rect.top + (clipH - tSize.cy) / 2;
				int width = rect.right - rect.left;
				if(tSize.cx < width){
                if (horizontalAlign == FCHorizontalAlign_Center){
					tRect.left = rect.left + (rect.right - rect.left - tSize.cx) / 2;
                }
                else if (horizontalAlign == FCHorizontalAlign_Right){
					tRect.left = rect.right - tSize.cx - 2;
                }
		}
				tRect.right = tRect.left + tSize.cx;
				tRect.bottom = tRect.top + tSize.cy;
				if(autoEllipsis && (tRect.right > clipRect.right || tRect.bottom > clipRect.bottom)){
					if(tRect.right < clipRect.right){
						tRect.right = clipRect.right;
					}
					if(tRect.bottom < clipRect.bottom){
						tRect.bottom = clipRect.bottom;
					}
					paint->drawTextAutoEllipsis(text, textColor, font, tRect);
				}
				else{
					paint->drawText(text, textColor, font, tRect, -1);
				}
			}
		}
	}

	void FCGridCell::onRemove(){
	}

    void FCGridCell::onScaling(double scaleFactorX, double scaleFactorY) {
        if (m_style) {
            if (m_style->m_font) {
                m_style->m_font->m_fontSize = (float)(m_style->m_font->m_fontSize * (scaleFactorX + scaleFactorY) / 2);
            }
        }
    }

	void FCGridCell::setBool(bool value){
	}

    void FCGridCell::setDouble(double value){
	}

    void FCGridCell::setFloat(float value){
	}

    void FCGridCell::setInt(int value){
	}

    void FCGridCell::setLong(Long value){
	}

	void FCGridCell::setAttribute(const String& name, const String& value){
		if (name == L"align"){
			if (!m_style){
                m_style = new FCGridCellStyle; 
            }
			m_style->setAlign(FCTran::strToHorizontalAlign(value));
        }
		else if(name == L"allowedit"){
			setAllowEdit(FCTran::strToBool(value));
		}
		else if (name == L"autoellipsis"){
			if (!m_style){
                m_style = new FCGridCellStyle; 
            }
			m_style->setAutoEllipsis(FCTran::strToBool(value));
        }
		else if(name == L"backcolor"){
			if (!m_style){
                m_style = new FCGridCellStyle; 
            }
            m_style->setBackColor(FCTran::strToColor(value));
		}
		else if (name == L"colspan"){
            setColSpan(FCTran::strToInt(value));
        }
		else if(name == L"font"){
			if (!m_style){
                m_style = new FCGridCellStyle; 
            }
			FCFont nFont = FCTran::strToFont(value);
            m_style->setFont(&nFont);
		}
		else if(name == L"textcolor"){
			if (!m_style){
                m_style = new FCGridCellStyle; 
            }
            m_style->setTextColor(FCTran::strToColor(value));
		}
		else if(name == L"name"){
			setName(value);
		}
        else if (name == L"rowspan"){
            setRowSpan(FCTran::strToInt(value));
        }
		else if(name == L"text"){
			setText(value);
		}
	}

    void FCGridCell::setString(const String& value){
	}

	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	FCGridViewCell::FCGridViewCell(){
		m_view = 0;
	}

	FCGridViewCell::~FCGridViewCell(){
		if(m_view){
			delete m_view;
			m_view = 0;			
		}
	}

	FCView* FCGridViewCell::getView(){
		return m_view;
	}

	void FCGridViewCell::setView(FCView *view){
		m_view = view;
	}

	String FCGridViewCell::getPaintText(){
		return L"";
	}

	String FCGridViewCell::getString(){
		if(m_view){
			return m_view->getText();
		}
		else{
			return L"";
		}
	}

	void FCGridViewCell::callTouchEvent(String eventName, Object sender, FCTouchInfo touchInfo, Object invoke){
		if (sender == m_view) {
			if (eventName == L"ontouchdown") {
                onViewTouchDown(touchInfo);
            } else if (eventName == L"ontouchmove") {
                onViewTouchMove(touchInfo);
            } else if (eventName == L"ontouchup") {
                onViewTouchUp(touchInfo);
            } else if (eventName == L"ontouchwheel") {
                onViewTouchWheel(touchInfo);
            }
        }
	}

	void FCGridViewCell::onAdd(){
		FCGrid *grid = getGrid();
	    if (m_view && grid){
            grid->addView(m_view);
			m_view->addEvent((FCTouchEventCallBack*)this, L"ontouchdown", this);
			m_view->addEvent((FCTouchEventCallBack*)this, L"ontouchmove", this);
			m_view->addEvent((FCTouchEventCallBack*)this, L"ontouchup", this);
			m_view->addEvent((FCTouchEventCallBack*)this, L"ontouchwheel", this);
        }
	}

	void FCGridViewCell::onViewTouchDown(FCTouchInfo touchInfo){
		FCGrid *grid = getGrid();
		if(grid && m_view){
			FCTouchInfo newTouchInfo = touchInfo;
            newTouchInfo.m_firstPoint = grid->pointToView(m_view->pointToNative(newTouchInfo.m_firstPoint));
            newTouchInfo.m_secondPoint = grid->pointToView(m_view->pointToNative(newTouchInfo.m_secondPoint));
			grid->onTouchDown(newTouchInfo);
		}
	}

	void FCGridViewCell::onViewTouchMove(FCTouchInfo touchInfo){
		FCGrid *grid = getGrid();
		if(grid && m_view){
			FCTouchInfo newTouchInfo = touchInfo;
            newTouchInfo.m_firstPoint = grid->pointToView(m_view->pointToNative(newTouchInfo.m_firstPoint));
            newTouchInfo.m_secondPoint = grid->pointToView(m_view->pointToNative(newTouchInfo.m_secondPoint));
			grid->onTouchMove(newTouchInfo);
		}
	}
	
	void FCGridViewCell::onViewTouchUp(FCTouchInfo touchInfo){
		FCGrid *grid = getGrid();
		if(grid && m_view){
			FCTouchInfo newTouchInfo = touchInfo;
            newTouchInfo.m_firstPoint = grid->pointToView(m_view->pointToNative(newTouchInfo.m_firstPoint));
            newTouchInfo.m_secondPoint = grid->pointToView(m_view->pointToNative(newTouchInfo.m_secondPoint));
			grid->onTouchUp(newTouchInfo);
		}
	}

	void FCGridViewCell::onViewTouchWheel(FCTouchInfo touchInfo){
		FCGrid *grid = getGrid();
		if(grid && m_view){
			FCTouchInfo newTouchInfo = touchInfo;
            newTouchInfo.m_firstPoint = grid->pointToView(m_view->pointToNative(newTouchInfo.m_firstPoint));
            newTouchInfo.m_secondPoint = grid->pointToView(m_view->pointToNative(newTouchInfo.m_secondPoint));
			grid->onTouchWheel(newTouchInfo);
		}
	}

	void FCGridViewCell::onPaint(FCPaint *paint, const FCRect& rect, const FCRect& clipRect, bool isAlternate){
		FCGridCell::onPaint(paint, rect, clipRect, isAlternate);
		onPaintView(paint, rect, clipRect);
	}

	void FCGridViewCell::onPaintView(FCPaint *paint, const FCRect& rect, const FCRect& clipRect){
		if (m_view){
			FCRect bounds = {rect.left + 1, rect.top + 1, rect.right - 1, rect.bottom - 1};
            m_view->setBounds(bounds);
			FCRect newClipRect = clipRect;
			newClipRect.left -= rect.left;
			newClipRect.top -=  rect.top;
			newClipRect.right -= rect.left;
			newClipRect.bottom -= rect.top;
			m_view->setRegion(newClipRect);
        }
	}

	void FCGridViewCell::onRemove(){
		FCGrid *grid = getGrid();
	    if (m_view && grid){
			m_view->removeEvent((FCTouchEventCallBack*)this, L"ontouchdown");
			m_view->removeEvent((FCTouchEventCallBack*)this, L"ontouchmove");
			m_view->removeEvent((FCTouchEventCallBack*)this, L"ontouchup");
			m_view->removeEvent((FCTouchEventCallBack*)this, L"ontouchwheel");
			grid->removeView(m_view);
			grid->getNative()->removeView(m_view);
		}
	}

	void FCGridViewCell::setString(const String& value){
		if(m_view){
			return m_view->setText(value);
		}
	}
}